`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    13:21:31 11/07/2012 
// Design Name: 
// Module Name:    LPF_BLOCK 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module LPF_BLOCK #(parameter LOG_LEN=8, LEN=129, WIDTH=16, OFFSET=0)
(
	input clk_1_x,
	input clk_len_x,
	input rst,
	input signed[WIDTH-1:0] in_data_r,
	input signed[WIDTH-1:0] in_data_i,
	output signed[WIDTH-1:0] out_r,
	output signed[WIDTH-1:0] out_i
    );
	 
	 
	 wire[LOG_LEN-1:0] addr_lpf_rom;
	 wire signed[WIDTH-1:0] out_lpf_rom_r;//rom out to ctr
	 wire signed[WIDTH-1:0] out_lpf_rom_i;
	 wire signed[WIDTH-1:0] lpf_rom_r;//ctr out
	 wire signed[WIDTH-1:0] lpf_rom_i;
	 
	 wire[LOG_LEN-1:0] addr_lpf_ram_wr;
	 wire[LOG_LEN-1:0] addr_lpf_ram_rd;
	 wire signed[WIDTH-1:0] lpf_ram_wr_r;//ctr out to ram
	 wire signed[WIDTH-1:0] lpf_ram_wr_i;
	 wire signed[WIDTH-1:0] lpf_ram_rd_r;//ram out to ctr
	 wire signed[WIDTH-1:0] lpf_ram_rd_i;
	 wire wr_en;
	 wire signed[WIDTH-1:0] lpf_ram_r;//ctr out
	 wire signed[WIDTH-1:0] lpf_ram_i;
	 
	 wire signed[WIDTH+WIDTH+1+LOG_LEN-1:0] tmp_out_r;//ALU out
	 wire signed[WIDTH+WIDTH+1+LOG_LEN-1:0] tmp_out_i;
	 
	 
	 LPF_PATTERN_ROM U_lpf_rom_r(
	 .clka(clk_len_x),
	 .addra(addr_lpf_rom),
	 .douta(out_lpf_rom_r)
	 );
	 
	 LPF_PATTERN_ROM U_lpf_rom_i(
	 .clka(clk_len_x),
	 .addra(addr_lpf_rom),
	 .douta(out_lpf_rom_i)
	 );
	 
	 ROM_CTR #(LOG_LEN, LEN, WIDTH, OFFSET) U_rom_ctr(
		.clk(clk_len_x),
		.rst(rst),
		.in_data_r(out_lpf_rom_r),
		.out_data_r(lpf_rom_r),
		.in_data_i(out_lpf_rom_i),
		.out_data_i(lpf_rom_i),
		.out_addr(addr_lpf_rom)
		);
		
	
	LPF_TMP_RAM U_lpf_ram_r(
		.clka(clk_len_x),
		.addra(addr_lpf_ram_wr),
		.dina(lpf_ram_wr_r),
		.wea(wr_en),
		.clkb(clk_len_x),
		.addrb(addr_lpf_ram_rd),
		.doutb(lpf_ram_rd_r)
		);
		
		
	LPF_TMP_RAM U_lpf_ram_i(
		.clka(clk_len_x),
		.addra(addr_lpf_ram_wr),
		.dina(lpf_ram_wr_i),
		.wea(wr_en),
		.clkb(clk_len_x),
		.addrb(addr_lpf_ram_rd),
		.doutb(lpf_ram_rd_i)
		);	
		
	
	MEM_WR #(LOG_LEN, LEN, WIDTH) U_lpf_ram_wr
	(
		.clk(clk_1_x),
		.rst(rst),
		.in_r(in_data_r),
		.in_i(in_data_i),
		.out_r(lpf_ram_wr_r),
		.out_i(lpf_ram_wr_i),
		.addr(addr_lpf_ram_wr),
		.wr_en(wr_en)
    );
	 
	 
	MEM_RD #(LOG_LEN, LEN, WIDTH) U_lpf_ram_rd
	(
		.clk(clk_len_x),
		.rst(rst),
		.in_r(lpf_ram_rd_r),
		.in_i(lpf_ram_rd_i),
		.addr_wr(addr_lpf_ram_wr),
		.out_r(lpf_ram_r),
		.out_i(lpf_ram_i),
		.addr(addr_lpf_ram_rd)
    );
		
		
	MUL_SUM_UNIT #(LOG_LEN, LEN, WIDTH) U_conv(
		.clk(clk_len_x),
		.rst(rst),
		.a_r(lpf_ram_r),
		.a_i(lpf_ram_i),
		.b_r(lpf_rom_r),
		.b_i(lpf_rom_i),
		.out_r(tmp_out_r),
		.out_i(tmp_out_i)
		);
		
	
	SCALE_UNIT #(WIDTH+WIDTH+1+LOG_LEN, WIDTH, WIDTH+WIDTH+1+LOG_LEN) U_scale_r(
	 .clk(clk_1_x),
	 .rst(rst),
	 .data_in(tmp_out_r),
	 .data_out(out_r)
	 );
	 
	 
	 SCALE_UNIT #(WIDTH+WIDTH+1+LOG_LEN, WIDTH, WIDTH+WIDTH+1+LOG_LEN) U_scale_i(
	 .clk(clk_1_x),
	 .rst(rst),
	 .data_in(tmp_out_i),
	 .data_out(out_i)
	 );

endmodule
